#include "maze_generator.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <chrono>
using namespace std;

MazeGenerator::MazeGenerator(int size) : size(size) {
    // 验证尺寸
    if (size < 7) {
        cout << "Warning: Size too small, setting to minimum size 7" << endl;
        this->size = 7;
    }
    
    // 初始化迷宫为全墙壁
    maze.resize(size, vector<GameElement>(size, GameElement(Position(0, 0), MazeElement::WALL, 0)));
    
    // 初始化随机数生成器
    unsigned seed = chrono::system_clock::now().time_since_epoch().count();
    rng.seed(seed);
}

void MazeGenerator::generateMaze() {
    cout << "Starting maze generation..." << endl;
    
    // 清空门的记录
    rows.clear();
    cols.clear();
    
    // 重置迷宫为全墙壁
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j) {
            maze[i][j] = GameElement(Position(i, j), MazeElement::WALL, 0);
        }
    }
    
    cout << "Maze initialized, starting divide and conquer..." << endl;
    
    // 使用分治法生成迷宫
    divideAndConquerRecursive(1, 1, size - 2, size - 2);
    
    cout << "Divide and conquer completed, placing game elements..." << endl;
    
    // 随机放置游戏元素
    placeGameElements();
    
    cout << "Maze generation completed!" << endl;
}

void MazeGenerator::divideAndConquerRecursive(int x1, int y1, int x2, int y2) {
    // 基础情况：区域太小
    if (x2 - x1 < 4 || y2 - y1 < 4) {
        return;
    }
    
    // 在区域内创建通路，并记录生成顺序
    for (int i = x1; i <= x2; ++i) {
        for (int j = y1; j <= y2; ++j) {
            // 保护S和E的位置不被覆盖
            // if (!(i == startPos.x && j == startPos.y) && !(i == endPos.x && j == endPos.y)) {
                
            // }
            maze[i][j] = GameElement(Position(i, j), MazeElement::PATH, 0);
        }
    }
    
    // 如果区域足够大，进行分割
    if (x2 - x1 > 2 && y2 - y1 > 2) {
        cout<<x1<<" "<<y1<<" "<<x2<<" "<<y2<<endl;

        // 选择分割点，避开已有门的位置
        int midX = (x1 + x2) / 2;
        int midY = (y1 + y2) / 2;
        
        // 避开已有门的行
        int i = 1;
        while (!rows.empty() && find(rows.begin(), rows.end(), midX) != rows.end()) {
            midX = x1 + i;
            i++;
        }
        
        // 避开已有门的列
        i = 1;
        while (!cols.empty() && find(cols.begin(), cols.end(), midY) != cols.end()) {
            midY = y1 + i;
            i++;
        }

        // 创建十字分割
        for (int i = x1; i <= x2; ++i) {
            maze[i][midY] = GameElement(Position(i, midY), MazeElement::WALL, 0);
        }
        for (int j = y1; j <= y2; ++j) {
            maze[midX][j] = GameElement(Position(midX, j), MazeElement::WALL, 0);
        }
        
        // 在四个象限的边界上各开一个门
        Position doors[4];
        
        // 上门
        int doorUp = (x1 + midX) / 2;
        maze[doorUp][midY] = GameElement(Position(doorUp,midY), MazeElement::PATH, 0);
        doors[0] = Position(doorUp, midY);
        rows.push_back(doorUp);

        // 下门
        int doorDown = (midX + x2) / 2;
        maze[doorDown][midY] = GameElement(Position(doorDown, midY), MazeElement::PATH, 0);
        doors[1] = Position(doorDown, midY);
        rows.push_back(doorDown);

        // 左门
        int doorLeft = (y1 + midY) / 2;
        maze[midX][doorLeft] = GameElement(Position(midX, doorLeft), MazeElement::PATH, 0);
        doors[2] = Position(midX, doorLeft);
        cols.push_back(doorLeft);

        // 右门
        int doorRight = (midY + y2) / 2;
        maze[midX][doorRight] = GameElement(Position(midX, doorRight), MazeElement::PATH, 0);
        doors[3] = Position(midX, doorRight);
        cols.push_back(doorRight);

        // 随机关闭一个门以保证连通性（确保只有一条路径）
        
            uniform_int_distribution<int> distClose(0, 3);
            int closeIndex = distClose(rng);
            Position closeDoor = doors[closeIndex];
            maze[closeDoor.x][closeDoor.y] = GameElement(closeDoor, MazeElement::WALL, 0);
            if(x1 == 1 && y1 == 1 && x2 == size - 2 && y2 == size - 2){
                cout<<"closeIndex: "<<closeIndex<<endl;
                if(closeIndex == 0){  // 上门被封闭
                    startPos = Position(x1, y1);  // 左上角
                    endPos = Position(x1, y2);    // 右上角
                    // 从记录中移除关闭的门
                    auto it = find(rows.begin(), rows.end(), doorUp);
                    if (it != rows.end()) rows.erase(it);
                    rows.push_back(x1);
                    cols.push_back(y1);
                    cols.push_back(y2);
                }
                else if(closeIndex == 1){  // 下门被封闭
                    startPos = Position(x2, y1);  // 左下角
                    endPos = Position(x2, y2);    // 右下角
                    // 从记录中移除关闭的门
                    auto it = find(rows.begin(), rows.end(), doorDown);
                    if (it != rows.end()) rows.erase(it);
                    rows.push_back(x2);
                    cols.push_back(y1);
                    cols.push_back(y2);
                }
                else if(closeIndex == 2){  // 左门被封闭
                    startPos = Position(x1, y1);  // 左上角
                    endPos = Position(x2, y1);    // 左下角
                    // 从记录中移除关闭的门
                    auto it = find(cols.begin(), cols.end(), doorLeft);
                    if (it != cols.end()) cols.erase(it);
                    rows.push_back(x1);
                    rows.push_back(x2);
                    cols.push_back(y1);
                }
                else if(closeIndex == 3){  // 右门被封闭
                    startPos = Position(x1, y2);  // 右上角
                    endPos = Position(x2, y2);    // 右下角
                    // 从记录中移除关闭的门
                    auto it = find(cols.begin(), cols.end(), doorRight);
                    if (it != cols.end()) cols.erase(it);
                    rows.push_back(x1);
                    rows.push_back(x2);
                    cols.push_back(y2);
                }
                // 设置起点和终点
                maze[startPos.x][startPos.y] = GameElement(startPos, MazeElement::START, 0);
                maze[endPos.x][endPos.y] = GameElement(endPos, MazeElement::EXIT, 0);
            }
        
        // 递归处理四个子区域
        divideAndConquerRecursive(x1, y1, midX - 1, midY - 1);
        divideAndConquerRecursive(x1, midY + 1, midX - 1, y2);
        divideAndConquerRecursive(midX + 1, y1, x2, midY - 1);
        divideAndConquerRecursive(midX + 1, midY + 1, x2, y2);
    }
}

void MazeGenerator::placeGameElements() {
    // 收集除起点和终点外的所有空位置
    vector<Position> emptyPositions;
    for (int i = 1; i < size - 1; ++i) {
        for (int j = 1; j < size - 1; ++j) {
            if (maze[i][j].type == MazeElement::PATH && 
                !(i == startPos.x && j == startPos.y) && 
                !(i == endPos.x && j == endPos.y)) {
                emptyPositions.emplace_back(i, j);
            }
        }
    }
    
    // 安全性检验：确保有剩余位置放置游戏元素
    // if (emptyPositions.empty()) {
    //     cout << "Warning: No remaining positions for game elements" << endl;
    // }

    // 随机打乱位置
    shuffle(emptyPositions.begin(), emptyPositions.end(), rng);
    
    // 放置资源（金币），金币所在位置至少为3，且不超过迷宫总位置的1/3
    int numResources = min(max(3, size / 3), static_cast<int>(emptyPositions.size()) / 3);
    numResources = min(numResources, static_cast<int>(emptyPositions.size())); // 额外安全检查
    
    for (int i = 0; i < numResources && i < static_cast<int>(emptyPositions.size()); ++i) {
        Position pos = emptyPositions[i];
        // 边界检查
        if (pos.x >= 0 && pos.x < size && pos.y >= 0 && pos.y < size) {
            maze[pos.x][pos.y] = GameElement(pos, MazeElement::GOLD, 5);
        }
    }
    
    // 放置陷阱，陷阱所在位置至少为2，且不超过迷宫总位置的1/5
    int startIndex = numResources;
    
    int numTraps = min(max(2, size / 5), 
                       static_cast<int>(emptyPositions.size() - startIndex) / 2);
    numTraps = min(numTraps, static_cast<int>(emptyPositions.size() - startIndex)); // 额外安全检查
    
    for (int i = 0; i < numTraps && (startIndex + i) < static_cast<int>(emptyPositions.size()); ++i) {
        Position pos = emptyPositions[startIndex + i];
        // 边界检查
        if (pos.x >= 0 && pos.x < size && pos.y >= 0 && pos.y < size) {
            maze[pos.x][pos.y] = GameElement(pos, MazeElement::TRAP, -3);
        }
    }
    
    // 放置机关，机关所在位置至少为2，且不超过迷宫总位置的1/2
    startIndex += numTraps;
    
    int numLockers = min(2, static_cast<int>(emptyPositions.size() - startIndex) / 2);
    numLockers = min(numLockers, static_cast<int>(emptyPositions.size() - startIndex)); // 额外安全检查
    
    for (int i = 0; i < numLockers && (startIndex + i) < static_cast<int>(emptyPositions.size()); ++i) {
        Position pos = emptyPositions[startIndex + i];
        // 边界检查
        if (pos.x >= 0 && pos.x < size && pos.y >= 0 && pos.y < size) {
            maze[pos.x][pos.y] = GameElement(pos, MazeElement::LOCKER, 0);
        }
    }
    
    // 放置BOSS，BOSS所在位置至少为1，且不超过迷宫总位置的1/2
    startIndex += numLockers;
    if (startIndex < static_cast<int>(emptyPositions.size())) {
        Position pos = emptyPositions[startIndex];
        // 边界检查
        if (pos.x >= 0 && pos.x < size && pos.y >= 0 && pos.y < size) {
            int attack = rng() % 10 + 1;
            maze[pos.x][pos.y] = GameElement(pos, MazeElement::BOSS, attack);
        }
    }
    
    // 最后重新设置起点和终点，确保它们显示在迷宫中
    if (startPos.x >= 0 && startPos.x < size && startPos.y >= 0 && startPos.y < size) {
        maze[startPos.x][startPos.y] = GameElement(startPos, MazeElement::START, 0);
    }
    if (endPos.x >= 0 && endPos.x < size && endPos.y >= 0 && endPos.y < size) {
        maze[endPos.x][endPos.y] = GameElement(endPos, MazeElement::EXIT, 0);
    }
}

bool MazeGenerator::isValidPosition(int x, int y) const {
    return x >= 0 && x < size && y >= 0 && y < size;
}


void MazeGenerator::printMaze() const {
    cout << "Generated Maze (" << size << "x" << size << "):" << endl;
    cout << string(size * 2 + 1, '-') << endl;
    
    for (int i = 0; i < size; ++i) {
        cout << "|";
        for (int j = 0; j < size; ++j) {
            cout << static_cast<char>(maze[i][j].type) << " ";
        }
        cout << "|" << endl;
    }
    
    cout << string(size * 2 + 1, '-') << endl;
    
    // 打印游戏元素信息
    cout << "\nGame Elements:" << endl;
    cout << "Start: (" << startPos.x << ", " << startPos.y << ")" << endl;
    cout << "End: (" << endPos.x << ", " << endPos.y << ")" << endl;
    
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j) {
            const GameElement& element = maze[i][j];
            if (element.type != MazeElement::WALL && element.type != MazeElement::PATH) {
                cout << "Element at (" << element.pos.x << ", " << element.pos.y 
                      << "): " << static_cast<char>(element.type) 
                      << " (value: " << element.value << ")" << endl;
            }
        }
    }
}

void MazeGenerator::saveToJSON(const string& filename) const {
    ofstream file(filename);
    if (!file.is_open()) {
        cerr << "Error: Cannot open file " << filename << endl;
        return;
    }
    
    file << "{\n";
    file << "  \"size\": " << size << ",\n";
    file << "  \"maze\": [\n";
    
    for (int i = 0; i < size; ++i) {
        file << "    \"";
        for (int j = 0; j < size; ++j) {
            file << static_cast<char>(maze[i][j].type);
        }
        file << "\"" << (i < size - 1 ? "," : "") << "\n";
    }
    
    file << "  ],\n";
    file << "  \"start_pos\": [" << startPos.x << ", " << startPos.y << "],\n";
    file << "  \"end_pos\": [" << endPos.x << ", " << endPos.y << "],\n";
    file << "  \"game_elements\": [\n";
    
    bool first = true;
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j) {
            const GameElement& element = maze[i][j];
            if (element.type != MazeElement::WALL && element.type != MazeElement::PATH) {
                if (!first) file << ",\n";
                file << "    {\n";
                file << "      \"position\": [" << element.pos.x << ", " << element.pos.y << "],\n";
                file << "      \"type\": \"" << static_cast<char>(element.type) << "\",\n";
                file << "      \"value\": " << element.value << "\n";
                file << "    }";
                first = false;
            }
        }
    }
    
    file << "\n  ]\n";
    file << "}\n";
    
    file.close();
    cout << "Maze saved to " << filename << endl;
}

void MazeGenerator::saveToCSV(const string& filename) const {
    ofstream file(filename);
    if (!file.is_open()) {
        cerr << "Error: Cannot open file " << filename << endl;
        return;
    }
    
    // 保存迷宫矩阵
    for (int i = 0; i < size; ++i) {
        for (int j = 0; j < size; ++j) {
            file << static_cast<char>(maze[i][j].type);
            if (j < size - 1) file << ",";
        }
        file << "\n";
    }
    
    file.close();
    cout << "Maze saved to " << filename << endl;
} 

